package com.neusoft.neuiotms.dcvm.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.Lists;
import com.neusoft.bizcore.web.dto.result.PageResultDTO;
import com.neusoft.bizcore.web.dto.result.ResultDTO;
import com.neusoft.bizcore.web.dto.result.ResultListDTO;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.dcvm.bean.LocationCiBean;
import com.neusoft.neuiotms.dcvm.bean.LocationCiTreeBean;
import com.neusoft.neuiotms.dcvm.converter.AlarmConverter;
import com.neusoft.neuiotms.dcvm.dto.AlarmDTO;
import com.neusoft.neuiotms.dcvm.model.Alarm;
import com.neusoft.neuiotms.dcvm.repository.AlarmRepository;
import com.neusoft.neuiotms.dcvm.service.LocationService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@Api("告警管理")
@Slf4j
@RestController
@RequestMapping(value = "/api/w/alarms")
public class AlarmController {
    @Autowired
    private LocationService locationService;
    @Autowired
    private AlarmRepository alarmRepository;
    @Autowired
    private AlarmConverter alarmConverter;

    @ApiOperation("获取所有告警")
    @GetMapping
    public ResultListDTO<?> index(final Searchable searchable) {
        if (searchable.hasKey("parentLocationCode")) {
            final String locationCode = searchable.getStrValue("parentLocationCode");

            final List<LocationCiBean> locationList = this.locationService.getDeepLocationsByOne(locationCode, 1000);
            final List<String> locationCodeList =
                    locationList.stream().map(it -> it.getCode()).collect(Collectors.toList());
            AlarmController.log.info("{}", String.join(",", locationCodeList));
            searchable.put("locationCodeList", locationCodeList);
        }
        final List<Alarm> models = this.alarmRepository.search(searchable);
        final List<AlarmDTO> dtos = this.alarmConverter.toListDTO(models);
        return ResultListDTO.success(dtos);
    }

    @ApiOperation("分页查询所有告警")
    @GetMapping("/p")
    public PageResultDTO<AlarmDTO> search(final Pageable pageable, final Searchable searchable) {

        if (searchable.hasKey("parentLocationCode")) {
            final String locationCode = searchable.getStrValue("parentLocationCode");

            final List<LocationCiBean> locationList = this.locationService.getDeepLocationsByOne(locationCode, 1000);
            final List<String> locationCodeList =
                    locationList.stream().map(it -> it.getCode()).collect(Collectors.toList());
            AlarmController.log.info("{}", String.join(",", locationCodeList));
            searchable.put("locationCodeList", locationCodeList);
        }

        final Page<Alarm> models = this.alarmRepository.search(pageable, searchable);
        final Page<AlarmDTO> dtos = this.alarmConverter.toPageDTO(models);
        return PageResultDTO.success(dtos);
    }

    @ApiOperation("根据位置统计")
    @GetMapping("/{location}/count")
    public ResultDTO<?> countOfSubLocation(@PathVariable final String location) {
        final LocationCiTreeBean tree = this.locationService.getLocationsTree(location);
        final List<LocationCiTreeBean> children = tree.getChildren();

        final Map<String, List<String>> parentChildrenPair = new HashMap<>();
        children.forEach(child -> {
            final List<String> childchildren = new ArrayList<>();
            this.getNextChildren(childchildren, child);
            parentChildrenPair.put(child.getCode(), childchildren);

        });

        final List<Map<String, Object>> result = new ArrayList<>();

        for (final Map.Entry<String, List<String>> entry : parentChildrenPair.entrySet()) {
            long count = 0;
            if (entry.getValue().size() > 0) {
                count = this.alarmRepository.countByLocationCodeIn(entry.getValue());
            }
            final Map<String, Object> map = new HashMap<>();
            map.put("location", entry.getKey());
            map.put("count", count);
            result.add(map);
        }

        //        final List<LocationCiBean> locations = this.locationService.getDeepLocationsByOne(location, Integer.MAX_VALUE);
        //        final List<String> codeArr =
        //                locations.stream().map(it -> it.getCode()).filter(it -> !location.equals(it))
        //                        .collect(Collectors.toList());
        //        long count = 0;
        //        if (codeArr.size() > 0) {
        //            count = this.alarmRepository.countByLocationCodeIn(codeArr);
        //        }
        return ResultDTO.success(result);
    }

    @ApiOperation("根据位置查找有告警的所有设备")
    @GetMapping("/{location}/list/deep/{deep}")
    public ResultListDTO<?> listOfLocation(@PathVariable final String location, @PathVariable final Integer deep) {
        final List<LocationCiBean> locations = this.locationService.getDeepLocationsByOne(location, deep);

        if (locations.size() == 0) {

        }
        final List<String> locationCodeArray = locations.stream().map(it -> it.getCode()).collect(Collectors.toList());

        final List<Alarm> alarms = this.alarmRepository.findByLocationCodeIn(locationCodeArray);

        final List<String> results = Lists.newArrayList();
        alarms.stream().forEach(it -> {
            results.add(it.getAssetCode());
            if (StringUtils.isNoneEmpty(it.getCabinetCode())) {
                results.add(it.getCabinetCode());
            }
        });

        //        final List<String> alarmAssetCodeArray =
        //                alarms.stream().map(it -> it.getAssetCode()).distinct().collect(Collectors.toList());

        return ResultListDTO.success(results.stream().distinct().collect(Collectors.toList()));
    }

    @ApiOperation("根据机柜查找有告警的所有设备")
    @GetMapping("/cabinet/{cabinet}/list")
    public ResultListDTO<?> listOfCabinet(@PathVariable final String cabinet) {

        final List<Alarm> alarms = this.alarmRepository.findByCabinetCode(cabinet);
        final List<String> alarmAssetCodeArray =
                alarms.stream().map(it -> it.getAssetCode()).distinct().collect(Collectors.toList());

        return ResultListDTO.success(alarmAssetCodeArray);
    }

    @ApiOperation("根据位置统计")
    @GetMapping("/stats/by/location")
    public ResultListDTO<?> statsByLocation() {
        final List<Map<String, Object>> result = this.alarmRepository.statsByLocation();
        return ResultListDTO.success(result);
    }

    @ApiOperation("获取监控数据")
    @GetMapping("/{assetCode}")
    public ResultListDTO<?> assetAlarms(@PathVariable final String assetCode) {
        final List<Alarm> models = this.alarmRepository.findByAssetCode(assetCode);
        final List<AlarmDTO> dtos = this.alarmConverter.toListDTO(models);
        return ResultListDTO.success(dtos);
    }

    private void getNextChildren(final List<String> codeArr, final LocationCiTreeBean child) {
        if (null != child) {
            codeArr.add(child.getCode());
        }
        if (null != child.getChildren()) {
            for (final LocationCiTreeBean ci : child.getChildren()) {
                this.getNextChildren(codeArr, ci);
            }
        }
    }
}
